package com.sheledon.flyCat.core.ioc;

import com.sheledon.flyCat.annotation.aop.Aspect;
import com.sheledon.flyCat.annotation.boot.Component;
import com.sheledon.flyCat.annotation.ioc.Configuration;
import com.sheledon.flyCat.annotation.springmvc.RestController;
import com.sheledon.flyCat.common.utils.BeanHelper;
import com.sheledon.flyCat.core.aop.factory.AopProxyProcessorFactory;
import com.sheledon.flyCat.core.aop.intercept.BeanProcessor;
import com.sheledon.flyCat.core.exception.BeanCreationException;
import com.sheledon.flyCat.core.exception.InitializeObjectException;
import com.sheledon.flyCat.core.exception.LoadBeanException;
import com.sheledon.flyCat.factory.ClassFactory;

import java.beans.Beans;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * IOC
 * constructor+constructor 循环依赖不可以解决
 * 需要设计递归
 * @author sheledon
 */
public class BeanFactory {
    // classname ---> instance
    // IOC容器，保存实例化并且完成属性注入的实例
    public static final Map<String,Object> BEANS = new ConcurrentHashMap<>();
    public static final Map<String,Object> PROXY_BEANS = new ConcurrentHashMap<>();
    public static void  loadAllBeans(){
        ClassFactory.CLASS_FACTORY.get(Component.class).forEach(BeanFactory::loadBean);
        ClassFactory.CLASS_FACTORY.get(RestController.class).forEach(BeanFactory::loadBean);
        verifyAllBeanValid();
    }
    public static Object getBean(Class<?> clazz){
        String beanName = BeanHelper.getBeanName(clazz);
        return BEANS.get(beanName);
    }
    public static Object getBean(String name){
        return BEANS.get(name);
    }
    public static Object getProxyBean(String name){
        return PROXY_BEANS.get(name);
    }
    public static Object getProxyBean(Class<?> clazz){
        String beanName = BeanHelper.getBeanName(clazz);
        return PROXY_BEANS.get(beanName);
    }
    public static <T> T getBean(String name,Class<T> clazz){
        return clazz.cast(BEANS.get(name));
    }

    public static void addBean(String name,Object bean){
        if (BEANS.containsKey(name)){
            throw new BeanCreationException("bean : "+name+" already exists , "+bean.getClass());
        }
        BEANS.put(name,bean);
    }
    public static void loadBean(Class<?> clazz){
        String beanName = BeanHelper.getBeanName(clazz);
        if(BEANS.get(beanName)==null){
            Object beanInstance = SingletonRegister.registerSingleton(beanName,clazz);
            //实现动态代理类的生成
            BeanProcessor beanProcessor = AopProxyProcessorFactory.get(clazz);
            Object proxyInstance = beanProcessor.postProcessAfterInitialization(beanInstance);
            BEANS.put(beanName,beanInstance);
            if (proxyInstance!=beanInstance){
                PROXY_BEANS.put(beanName,proxyInstance);
            }
        }else{
            throw new LoadBeanException(String.format("%s already exists",beanName));
        }
    }
    //验证所有的bean是否合法，即检查二级缓存中所有的bean和在完成所有加载动作之后的IOC容器中的bean是否一致
    //如果一致，直接将二级缓存 GC
    private static void verifyAllBeanValid(){
        SingletonRegister.earlySingletonObjects.forEach((name,bean)->{
            if (!BEANS.containsKey(name)){
                throw new InitializeObjectException("verify not found bean :"+name);
            }
        });
    }
}
